use crate::{bootstrap::AppState, middleware::jwt::admin::Claims, router::resp::RespVO, service};
use axum::{
    body::Body,
    extract::{Path, Query, State},
    http::Response,
    response::IntoResponse,
    Json,
};
use sea_orm::error;
use serde::{Deserialize, Serialize};
use sky_common::constant;
use sky_pojo::{
    dto::{
        self,
        order::{
            OrderCancelDTO, OrderConfirmDTO, OrderPageQueryDTO, OrderPaymentDTO, OrderPaymentVO,
            OrderRejectionDTO, OrdersPageQueryDTO, OrdersSubmitDTO,
        },
    },
    entities::order_detail,
    vo::{
        order::{OrderStatisticsVO, OrderSubmitVO, OrderVO},
        PageResult,
    },
};

pub async fn condition_search(
    State(state): State<AppState>,
    _claim: Claims,
    Json(dto): Json<OrdersPageQueryDTO>,
) -> Response<Body> {
    match service::order::condition_search(&state.db_pool, dto).await {
        Ok(model) => RespVO::<PageResult<OrderVO>>::success("success".to_owned(), Some(model))
            .into_response(),
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn statistics(State(state): State<AppState>, _claim: Claims) -> Response<Body> {
    match service::order::statistics(&state.db_pool).await {
        Ok(vo) => {
            RespVO::<OrderStatisticsVO>::success("success".to_owned(), Some(vo)).into_response()
        }
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DetailsDTO {
    pub id: i64,
}
pub async fn details(
    State(state): State<AppState>,
    Path(details): Path<DetailsDTO>,
) -> Response<Body> {
    match service::order::details(&state.db_pool, details.id).await {
        Ok(vo) => RespVO::<OrderVO>::success("success".to_owned(), Some(vo)).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err).into_response(),
    }
}

pub async fn confirm(
    State(state): State<AppState>,
    _claim: Claims,
    Json(dto): Json<OrderConfirmDTO>,
) -> Response<Body> {
    match service::order::status_eq(
        &state.db_pool,
        dto.id.to_string(),
        constant::order::TO_BE_CONFIRMED,
    )
    .await
    {
        Ok(bool) => match bool {
            true => match service::order::confirm(&state.db_pool, dto).await {
                Ok(_) => {
                    return RespVO::<()>::success_without_data("success".to_string())
                        .into_response()
                }
                Err(err) => {
                    return RespVO::<()>::error_without_data(err.to_owned()).into_response()
                }
            },

            false => {
                RespVO::<()>::error_without_data(constant::message::ORDER_STATUS_ERROR.to_owned())
                    .into_response()
            }
        },
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn rejection(
    State(state): State<AppState>,
    _claim: Claims,
    Json(dto): Json<OrderRejectionDTO>,
) -> Response<Body> {
    match service::order::rejection(&state.db_pool, dto).await {
        Ok(_) => RespVO::<()>::success_without_data("success".to_string()).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err.to_owned()).into_response(),
    }
}

pub async fn cancel(
    State(state): State<AppState>,
    _claim: Claims,
    Json(dto): Json<OrderCancelDTO>,
) -> Response<Body> {
    match service::order::cancel(&state.db_pool, dto).await {
        Ok(_) => RespVO::<()>::success_without_data("success".to_string()).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err.to_owned()).into_response(),
    }
}

pub async fn delivery(
    State(state): State<AppState>,
    _claim: Claims,
    Path(id): Path<i64>,
) -> Response<Body> {
    match service::order::status_eq(&state.db_pool, id.to_string(), constant::order::CONFIRMED)
        .await
    {
        Ok(bool) => match bool {
            true => {}
            false => {
                return RespVO::<()>::error_without_data(
                    constant::message::ORDER_STATUS_ERROR.to_owned(),
                )
                .into_response()
            }
        },
        Err(e) => return RespVO::<()>::error_without_data(e).into_response(),
    }

    match service::order::delivery(&state.db_pool, id).await {
        Ok(_) => RespVO::<()>::success_without_data("success".to_string()).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err.to_owned()).into_response(),
    }
}

pub async fn complete(
    State(state): State<AppState>,
    _claim: Claims,
    Path(id): Path<i64>,
) -> Response<Body> {
    match service::order::status_eq(
        &state.db_pool,
        id.to_string(),
        constant::order::DELIVERY_IN_PROGRESS,
    )
    .await
    {
        Ok(bool) => match bool {
            true => {}
            false => {
                return RespVO::<()>::error_without_data(
                    constant::message::ORDER_STATUS_ERROR.to_owned(),
                )
                .into_response()
            }
        },
        Err(e) => return RespVO::<()>::error_without_data(e).into_response(),
    }
    match service::order::complete(&state.db_pool, id).await {
        Ok(_) => RespVO::<()>::success_without_data("success".to_string()).into_response(),
        Err(err) => RespVO::<()>::error_without_data(err.to_owned()).into_response(),
    }
}
